`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    11:29:50 10/24/2012 
// Design Name: 
// Module Name:    CONV_CORR_UNIT 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module CROSS_CORR_UNIT #(parameter LOG_CYCLE = 8, CYCLE = 150, WIDTH = 16) //cycle = 150
(

	 input clk_r_x,
	 input clk_r_len_x,
    input rst,
	 input signed [WIDTH-1:0] a_r,
    input signed [WIDTH-1:0] a_i,
    input signed [WIDTH-1:0] b_r,
    input signed [WIDTH-1:0] b_i,
	 output reg signed[WIDTH+WIDTH+1-1:0] coef_numerator,
	 output reg signed[WIDTH+WIDTH-1:0] coef_denominator
    );

	wire signed[WIDTH+WIDTH+1+LOG_CYCLE-1:0] sum_prod_r;
   wire signed[WIDTH+WIDTH+1+LOG_CYCLE-1:0] sum_prod_i;
	wire signed[WIDTH-1:0] sum_prod_r_scaled;
	wire signed[WIDTH-1:0] sum_prod_i_scaled;
	wire signed[WIDTH+WIDTH+1-1:0] var_a;
	wire signed[WIDTH+WIDTH+1-1:0] var_b;
	wire signed[WIDTH+WIDTH+1+LOG_CYCLE-1:0] sum_var_a;
	wire signed[WIDTH+WIDTH+1+LOG_CYCLE-1:0] sum_var_b;
	wire signed[WIDTH-1:0] sum_var_a_scaled;
	wire signed[WIDTH-1:0] sum_var_b_scaled;
	

	MUL_SUM_UNIT #(LOG_CYCLE, CYCLE, WIDTH) U_mul_sum //cycle = 160
	(
		.clk(clk_r_len_x), 
		.rst(rst), 
		.a_r(a_r), 
		.a_i(a_i), 
		.b_r(b_r), 
		.b_i(b_i),
		.out_r(sum_prod_r), 
		.out_i(sum_prod_i)
	);
	
	SCALE_UNIT #(WIDTH+WIDTH+1+LOG_CYCLE, WIDTH, WIDTH+WIDTH+1+LOG_CYCLE) U_scale_sprod_a
	(
		.clk(clk_r_len_x),
		.rst(rst),
		.data_in(sum_prod_r),
		.data_out(sum_prod_r_scaled)
    );
	 
	SCALE_UNIT #(WIDTH+WIDTH+1+LOG_CYCLE, WIDTH, WIDTH+WIDTH+1+LOG_CYCLE) U_scale_sprod_b
	(
		.clk(clk_r_len_x),
		.rst(rst),
		.data_in(sum_prod_i),
		.data_out(sum_prod_i_scaled)
    );
	
	
	////////////////////////////////////
	SQUARE_UNIT #(WIDTH) U_square_1
	(
		.clk(clk_r_len_x),
		.rst(rst),
		.a_r(a_r),
		.a_i(a_i),
		.out(var_a)
	);
	
	SQUARE_UNIT #(WIDTH) U_square_2
	(
		.clk(clk_r_len_x),
		.rst(rst),
		.a_r(b_r),
		.a_i(b_i),
		.out(var_b)
	);
	
	
	ACC_UNIT #(LOG_CYCLE, CYCLE, WIDTH+WIDTH+1) U_acc_1 //cycle = 160
	(
		.clk(clk_r_len_x),
		.rst(rst),
		.a_r(var_a),
		.a_i(var_b),
		.out_r(sum_var_a),
		.out_i(sum_var_b)
    );
	 
	SCALE_UNIT #(WIDTH+WIDTH+1+LOG_CYCLE, WIDTH, WIDTH+WIDTH+1+LOG_CYCLE) U_scale_svar_a
	(
		.clk(clk_r_len_x),
		.rst(rst),
		.data_in(sum_var_a),
		.data_out(sum_var_a_scaled)
    );
	 
	SCALE_UNIT #(WIDTH+WIDTH+1+LOG_CYCLE, WIDTH, WIDTH+WIDTH+1+LOG_CYCLE) U_scale_svar_b
	(
		.clk(clk_r_len_x),
		.rst(rst),
		.data_in(sum_var_b),
		.data_out(sum_var_b_scaled)
    );
		
		
	always@(posedge clk_r_x or negedge rst)
		if(!rst)
		begin
			coef_numerator <= 0;
			coef_denominator <= 0;
		end
		else
		begin
			coef_numerator <= (sum_prod_r_scaled*sum_prod_r_scaled + sum_prod_i_scaled*sum_prod_i_scaled);
			coef_denominator <= sum_var_a_scaled*sum_var_b_scaled;
		end
		

endmodule